#ifndef HEXEDITPANEL_H
#define HEXEDITPANEL_H

#include <wx/scrolbar.h>
#include <wx/checkbox.h>
#include <wx/sizer.h>
#include <wx/button.h>
#include <wx/menu.h>
#include <wx/panel.h>
#include <wx/statline.h>
#include <wx/stattext.h>
#include <wx/textctrl.h>
#include <wx/timer.h>
#include <editorbase.h>
#include <vector>
#include <set>
#include "FileContentBase.h"
#include "ExpressionPreprocessed.h"
#include "HexEditViewBase.h"

class DigitView;
class wxClientDC;

class HexEditPanel: public EditorBase {
  public:
    HexEditPanel( const wxString& fileName, const wxString& title );
    virtual ~HexEditPanel();
    static bool IsHexEditor( EditorBase* editor );
    static void CloseAllEditors();
  protected:
    virtual bool GetModified() const;
    virtual void SetModified( bool modified );
    virtual bool Save();
    virtual bool SaveAs();
    virtual void SetFilename( const wxString& filename );
  private:
    typedef FileContentBase::OffsetT OffsetT;
    wxMenuItem* MenuItem29;
    wxMenuItem* MenuItem2;
    wxMenu m_ColsModeMenu;
    wxMenuItem* MenuItem23;
    wxBoxSizer* PreviewSizer;
    wxMenu* MenuItem10;
    wxMenuItem* MenuItem31;
    wxMenuItem* MenuItem1;
    wxButton* m_ColsModeBtn;
    wxMenu* MenuItem19;
    wxFlexGridSizer* FlexGridSizer1;
    wxMenuItem* MenuItem30;
    wxTextCtrl* m_Expression;
    wxBoxSizer* BoxSizer3;
    wxStaticLine* StaticLine2;
    wxMenu m_EndianessMenu;
    wxStaticText* m_ExpressionVal;
    wxStaticText* m_LDoubleVal;
    wxMenuItem* MenuItem16;
    wxMenuItem* MenuItem12;
    wxMenuItem* MenuItem25;
    wxButton* m_BlockSize;
    wxScrollBar* m_ContentScroll;
    wxStaticText* m_FloatVal;
    wxMenuItem* MenuItem32;
    wxButton* Button4;
    wxMenuItem* MenuItem20;
    wxStaticText* m_DwordVal;
    wxButton* Button1;
    wxPanel* m_DrawArea;
    wxCheckBox* CheckBox1;
    wxButton* Button2;
    wxMenuItem* MenuItem33;
    wxButton* Button3;
    wxMenu m_BaseMenu;
    wxMenuItem* MenuItem24;
    wxBoxSizer* BoxSizer2;
    wxMenuItem* MenuItem15;
    wxStaticText* StaticText1;
    wxMenuItem* MenuItem21;
    wxMenuItem* MenuItem17;
    wxStaticText* StaticText3;
    wxMenu m_BlockSizeMenu;
    wxMenuItem* MenuItem3;
    wxStaticLine* StaticLine1;
    wxButton* Button5;
    wxMenuItem* MenuItem9;
    wxStaticText* StaticText8;
    wxStaticText* m_WordVal;
    wxBoxSizer* BoxSizer4;
    wxMenuItem* MenuItem11;
    wxMenu* MenuItem28;
    wxMenuItem* MenuItem22;
    wxMenuItem* MenuItem5;
    wxStaticText* StaticText4;
    wxTimer ReparseTimer;
    wxBoxSizer* BoxSizer1;
    wxStaticText* m_DoubleVal;
    wxStaticText* StaticText5;
    wxStaticText* StaticText2;
    wxMenuItem* MenuItem27;
    wxMenuItem* MenuItem18;
    wxMenuItem* MenuItem7;
    wxMenuItem* MenuItem6;
    wxMenuItem* MenuItem4;
    wxMenuItem* MenuItem26;
    wxStaticText* StaticText6;
    wxMenuItem* MenuItem13;
    wxStaticText* m_ByteVal;
    wxStaticText* m_Status;
    wxMenuItem* MenuItem8;
    wxButton* Button6;
    wxMenuItem* MenuItem14;
    wxButton* m_Endianess;
    wxButton* m_DigitBits;

    static const long ID_STATICTEXT1;
    static const long ID_BUTTON10;
    static const long ID_BUTTON9;
    static const long ID_STATICLINE2;
    static const long ID_BUTTON7;
    static const long ID_BUTTON4;
    static const long ID_BUTTON6;
    static const long ID_BUTTON5;
    static const long ID_STATICLINE1;
    static const long ID_BUTTON1;
    static const long ID_BUTTON8;
    static const long ID_CHECKBOX1;
    static const long ID_PANEL1;
    static const long ID_SCROLLBAR1;
    static const long ID_STATICTEXT2;
    static const long ID_STATICTEXT3;
    static const long ID_STATICTEXT4;
    static const long ID_STATICTEXT5;
    static const long ID_STATICTEXT6;
    static const long ID_STATICTEXT7;
    static const long ID_STATICTEXT8;
    static const long ID_STATICTEXT9;
    static const long ID_STATICTEXT10;
    static const long ID_STATICTEXT11;
    static const long ID_STATICTEXT12;
    static const long ID_STATICTEXT13;
    static const long ID_STATICTEXT14;
    static const long ID_TEXTCTRL1;
    static const long ID_BUTTON3;
    static const long ID_BUTTON2;
    static const long ID_STATICTEXT15;
    static const long ID_TIMER1;
    static const long ID_MENUITEM2;
    static const long ID_MENUITEM1;
    static const long ID_MENUITEM3;
    static const long ID_MENUITEM4;
    static const long ID_MENUITEM5;
    static const long ID_MENUITEM6;
    static const long ID_MENUITEM7;
    static const long ID_MENUITEM8;
    static const long ID_MENUITEM9;
    static const long ID_MENUITEM11;
    static const long ID_MENUITEM12;
    static const long ID_MENUITEM13;
    static const long ID_MENUITEM14;
    static const long ID_MENUITEM15;
    static const long ID_MENUITEM16;
    static const long ID_MENUITEM17;
    static const long ID_MENUITEM18;
    static const long ID_MENUITEM32;
    static const long ID_MENUITEM10;
    static const long ID_MENUITEM20;
    static const long ID_MENUITEM21;
    static const long ID_MENUITEM22;
    static const long ID_MENUITEM23;
    static const long ID_MENUITEM24;
    static const long ID_MENUITEM25;
    static const long ID_MENUITEM26;
    static const long ID_MENUITEM27;
    static const long ID_MENUITEM19;
    static const long ID_MENUITEM29;
    static const long ID_MENUITEM30;
    static const long ID_MENUITEM31;
    static const long ID_MENUITEM33;
    static const long ID_MENUITEM28;
    void OnContentPaint( wxPaintEvent& event );
    void OnContentSize( wxSizeEvent& event );
    void OnContentScroll( wxScrollEvent& event );
    void OnContentMouseWheel( wxMouseEvent& event );
    void OnDrawAreaKeyDown( wxKeyEvent& event );
    void OnDrawAreaEraseBackground( wxEraseEvent& event );
    void OnForwardFocus( wxFocusEvent& event );
    void OnDrawAreaLeftDown( wxMouseEvent& event );
    void OnDrawAreaLeftUp( wxMouseEvent& event );
    void OnDrawAreaMouseMove( wxMouseEvent& event );
    void OnCheckBox1Click( wxCommandEvent& event );
    void OnSpecialKeyDown( wxKeyEvent& event );
    void OnButton1Click( wxCommandEvent& event );
    void OnReparseTimerTrigger( wxTimerEvent& event );
    void Onm_ExpressionText( wxCommandEvent& event );
    void OnButton2Click( wxCommandEvent& event );
    void OnExpressionTextEnter( wxCommandEvent& event );
    void OnButton3Click( wxCommandEvent& event );
    void OnButton3Click1( wxCommandEvent& event );
    void OnButton4Click( wxCommandEvent& event );
    void OnSetBaseHex( wxCommandEvent& event );
    void OnSetBaseBin( wxCommandEvent& event );
    void Onm_EndianessClick( wxCommandEvent& event );
    void OnSetEndianessBig( wxCommandEvent& event );
    void OnSetEndianessLittle( wxCommandEvent& event );
    void Onm_BlockSizeClick( wxCommandEvent& event );
    void OnSetBlockSize1( wxCommandEvent& event );
    void OnSetBlockSize2( wxCommandEvent& event );
    void OnSetBlockSize4( wxCommandEvent& event );
    void OnSetBlockSize8( wxCommandEvent& event );
    void Onm_ColsModeClick( wxCommandEvent& event );
    void OnSetColsMul1( wxCommandEvent& event );
    void OnSetColsMul2( wxCommandEvent& event );
    void OnSetColsMul3( wxCommandEvent& event );
    void OnSetColsMul4( wxCommandEvent& event );
    void OnSetColsMul5( wxCommandEvent& event );
    void OnSetColsMul6( wxCommandEvent& event );
    void OnSetColsMul7( wxCommandEvent& event );
    void OnSetColsMul8( wxCommandEvent& event );
    void OnSetColsMulOther( wxCommandEvent& event );
    void OnSetColsValue1( wxCommandEvent& event );
    void OnSetColsValue2( wxCommandEvent& event );
    void OnSetColsValue3( wxCommandEvent& event );
    void OnSetColsValue4( wxCommandEvent& event );
    void OnSetColsValue5( wxCommandEvent& event );
    void OnSetColsValue6( wxCommandEvent& event );
    void OnSetColsValue7( wxCommandEvent& event );
    void OnSetColsValue8( wxCommandEvent& event );
    void OnSetColsValueOther( wxCommandEvent& event );
    void OnSetColsPower2( wxCommandEvent& event );
    void OnSetColsPower4( wxCommandEvent& event );
    void OnSetColsPower8( wxCommandEvent& event );
    void OnSetColsPowerOther( wxCommandEvent& event );
    void OnButton4Click1( wxCommandEvent& event );
    void OnContentScrollTop( wxScrollEvent& event );
    void OnContentScrollBottom( wxScrollEvent& event );
    void OnButton6Click( wxCommandEvent& event );
    void OnButton5Click( wxCommandEvent& event );
    typedef std::set< EditorBase* > EditorsSet;

    enum {
      VIEW_DIGIT,
      VIEW_CHARS,
      MAX_VIEWS
    };

    enum {
      CM_ANY,
      CM_MULT,
      CM_POWER,
      CM_SPECIFIED
    };

    wxString m_FileName;  // Name of the file being edited
    FileContentBase* m_Content; // Content structure of file being edited
    wxString m_ErrorString; // String containg error description (if couldn't read the content)
    wxFont* m_DrawFont;  // Font used for drawing
    wxCoord m_FontX;  // Width of character
    wxCoord m_FontY;  // Height of character
    unsigned int m_Cols; // Number of available characters in row in the editor
    unsigned int m_Lines;  // Number of available lines of characters in the editor
    unsigned int m_LineBytes; // Number of bytes shown in a line
    bool m_NeedRecalc;
    OffsetT m_Current; // Offset of current character
    wxString m_ExpressionError; // Last error reported while compiling user-defined expression in preview bar
    Expression::Preprocessed m_ExpressionCode;  // Bytecode of user-defined expression in preview bar
    HexEditViewBase* m_Views[ MAX_VIEWS ];  // List of all used views
    unsigned m_ViewsCols[ MAX_VIEWS ];  // Size of each view in characters
    HexEditViewBase* m_ActiveView;  // Index of active view
    DigitView* m_DigitView; // Cached pointer to digit view
    bool m_ViewNotifyContentChange;
    bool m_ViewNotifyOffsetChange;
    bool m_MouseDown;
    int m_ColsMode;
    int m_ColsValue;
    int m_ColsCount;
    OffsetT m_LinesPerScrollUnit;  // Number of lines per one scroll unit
    int m_LastScrollUnits; // Last position of the scroll (in scroll units)
    OffsetT m_LastScrollPos; // Last position of the scroll as offset in file
    static EditorsSet  m_AllEditors;
    void ReadContent();
    void RecalculateCoefs( wxDC &dc );
    FileContentBase::OffsetT DetectStartOffset();
    void RefreshStatus();
    void UpdateModified();
    void EnsureCarretVisible();
    void ClampCursorToVisibleArea();
    void ProcessGoto();
    void ProcessSearch();
    void ReparseExpression();
    inline void CreateViews();
    inline void ActivateView( HexEditViewBase* view );
    void PropagateOffsetChange( int flagsForCurrentView = -1 );
    inline void ViewNotifyContentChange() { m_ViewNotifyContentChange = true; }
    inline void ViewNotifyOffsetChange( OffsetT newOffset ) { m_Current = newOffset; m_ViewNotifyOffsetChange = true; }
    void DisplayChanged();
    void ColsMode( int mode, int value );
    bool MatchColumnsCount( int colsCount );
    friend class HexEditViewBase;
    virtual bool CanUndo() const;
    virtual bool CanRedo() const;
    virtual void Undo();
    virtual void Redo();

    DECLARE_EVENT_TABLE()
};

#endif
